//*************************************************************************\\
//***********               tdc_automata.cpp      		***********\\
//*************************************************************************\\
//*************************************************************************\\
//*********** 		        UFPE/Cin - Greco		***********\\
//*********** 		 http://www.cin.ufpe.br/~greco 		***********\\
//***********							***********\\
//***********							***********\\
//*********** 		    By Rafael Melo Macieira		***********\\
//***********							***********\\
//***********		    E-mail: rmm2@cin.ufpe.br		***********\\
//*************************************************************************\\
//*************************************************************************\\
//**		 Automata Reference for the temporal check		 **\\
//**	   	 VIRTUAL CLASS                                           **\\
//*************************************************************************\\

#include "headers/tdc_automata.h"
#include <stdio.h>

//################################ TDC_Automata #############################

void TDC_Automata::printRejection(StateID stateID){};
int TDC_Automata::checkState(StateID stateID){};
int TDC_Automata::checkInitialState(){};
TDC_Automata::StateID TDC_Automata::getNextState(StateID stateID){};
int TDC_Automata::runStep(bool access_type, VarList* currentVarList){};
void TDC_Automata::refreshVariables(VarList* currentVarList){};
void TDC_Automata::reset(){};
TDC_Automata::TDC_Automata(char* name){//, VarList mainVarList){
  this->name = name;
};

//################################## VARLIST ###############################

VarList::VarList(unsigned int platformAddr, unsigned int* var){
    this->platformAddr = platformAddr;
    this->var = var;
    //printf("\nInt Var: %p\n",var);
    this->EOL = 1;
};

void VarList::addNextVar(VarList* varList){
    this->nextVar = varList;
    this->EOL = 0;
};

VarList* VarList::getNextVar(){
    return this->nextVar;
};

unsigned int* VarList::getVar(){
    return this->var;
};

void VarList::setVar(unsigned int* var){
    //printf("\nSetVat Pre: Atual: %p - Proposto: %p\n", this->var, var);
    this->var = var;
    //printf("\nSetVat Pos: Atual: %p - proposto: %p\n", this->var, var);
};

bool VarList::isEOL(){
    return this->EOL;
};

unsigned int VarList::getPlatformAddr(){
    return this->platformAddr;
};

VarList* VarList::getVarListByPlatformAddr(VarList* mainVarList, unsigned int platformAddr) {
    VarList* tempvar = mainVarList;
    if (tempvar->isEOL()) {
        //printf(" Eh EOF(%i)\n ",platformAddr);
        //printf("mainint %p\n", &mainVarList);
        //printf("\nRetorna 1 SO MAIN %p", tempvar);
        return tempvar;
    } else {
        //printf(" !NAO Eh EOF(%i)\n ",platformAddr);
        VarList *next = tempvar->getNextVar();
        //printf("nextint %p\n", &mainVarList);
        while (!next->isEOL()) {
            if (tempvar->getPlatformAddr() == platformAddr) {
                //printf("\nRetorna PRIM. MAIN %p", tempvar);
                return tempvar;
            } else {
                tempvar = next;
                next = next->getNextVar();
            }
        }
        if (tempvar->getPlatformAddr() == platformAddr) {
            //printf("\nRetorna MAIN %p", tempvar->getVar());
            return tempvar;
        } else {
            //printf("\nRetorna NEXT %p", next->getVar());
            return next;
        }
    }
};

bool VarList::contains(VarList* mainVarList, unsigned int platformAddr){
    VarList* tempvar = mainVarList;
    if (tempvar->isEOL()) {
        //printf("Plataform Addr: %d = %d\n",mainVarList.getPlatformAddr(),platformAddr);
        if (tempvar->getPlatformAddr() == platformAddr){
            return 1;
        }else{
            return 0;
        }
    } else {
        VarList *next = tempvar->getNextVar();
        while (!next->isEOL()) {
            if (tempvar->getPlatformAddr() == platformAddr) {
                return 1;
            } else {
                tempvar = next;
                next = next->getNextVar();
            }
        }
        if (tempvar->getPlatformAddr() == platformAddr) {
            return 1;
        } else if (next->getPlatformAddr() == platformAddr) {
            return 1;
        }else{
            return 0;
        }
    }
};

//################################## AUTOMATALIST ###############################

AutomataList::AutomataList(unsigned int platformAddr, TDC_Automata* automata){
    this->platformAddr = platformAddr;
    this->automata = automata;
    //printf("\nInt Var: %p\n",var);
    this->EOL = 1;
};

void AutomataList::addNextAutomata(AutomataList* Automatalist){
    this->nextAutomata = Automatalist;
    this->EOL = 0;
};

AutomataList* AutomataList::getNextAutomata(){
    return this->nextAutomata;
};

TDC_Automata* AutomataList::getAutomata(){
    return this->automata;
};

void AutomataList::setAutomata(TDC_Automata* var){
    //printf("\nSetVat Pre: Atual: %p - Proposto: %p\n", this->var, var);
    this->automata = automata;
    //printf("\nSetVat Pos: Atual: %p - proposto: %p\n", this->var, var);
};

bool AutomataList::isEOL(){
    return this->EOL;
};

unsigned int AutomataList::getPlatformAddr(){
    return this->platformAddr;
};

AutomataList* AutomataList::getAutomataListByPlatformAddr(AutomataList* mainAutomataList, unsigned int platformAddr) {
    AutomataList* tempvar = mainAutomataList;
    if (tempvar->isEOL()) {
        //printf(" Eh EOF(%i)\n ",platformAddr);
        //printf("mainint %p\n", &mainAutomataList);
        //printf("\nRetorna 1 SO MAIN %p", tempvar);
        return tempvar;
    } else {
        //printf(" !NAO Eh EOF(%i)\n ",platformAddr);
        AutomataList *next = tempvar->getNextAutomata();
        //printf("nextint %p\n", &mainAutomataList);
        while (!next->isEOL()) {
            if (tempvar->getPlatformAddr() == platformAddr) {
                //printf("\nRetorna PRIM. MAIN %p", tempvar);
                return tempvar;
            } else {
                tempvar = next;
                next = next->getNextAutomata();
            }
        }
        if (tempvar->getPlatformAddr() == platformAddr) {
            //printf("\nRetorna MAIN %p", tempvar->getVar());
            return tempvar;
        } else {
            //printf("\nRetorna NEXT %p", next->getVar());
            return next;
        }
    }
};

bool AutomataList::contains(AutomataList* mainAutomataList, unsigned int platformAddr){
    AutomataList* tempvar = mainAutomataList;
    if (tempvar->isEOL()) {
        //printf("Plataform Addr: %d = %d\n",mainAutomataList.getPlatformAddr(),platformAddr);
        if (tempvar->getPlatformAddr() == platformAddr){
            return 1;
        }else{
            return 0;
        }
    } else {
        AutomataList *next = tempvar->getNextAutomata();
        while (!next->isEOL()) {
            if (tempvar->getPlatformAddr() == platformAddr) {
                return 1;
            } else {
                tempvar = next;
                next = next->getNextAutomata();
            }
        }
        if (tempvar->getPlatformAddr() == platformAddr) {
            return 1;
        } else if (next->getPlatformAddr() == platformAddr) {
            return 1;
        }else{
            return 0;
        }
    }
};
